#include "cbb_soft_tim.h"
#include <string.h>

// 定时器使能位
#define SOFT_TIM_EN_BIT 1 

Soft_Tim_t*
cbb_soft_tim_register(uint16_t u16Interval){

    // 申请定时器内存
    Soft_Tim_t* pstTim = (Soft_Tim_t*)SOFT_TIM_MALLOC(sizeof(Soft_Tim_t));
    if(pstTim == NULL) return NULL;
    
    // 初始化定时器参数
    pstTim->u16Interval = u16Interval;  // 定时器周期
    pstTim->u16Flag = 0;                // 定时器标志位
    pstTim->u16Tick = 0;                // 定时器周期计数

    // 返回定时器
    return pstTim;
}

SOFT_TIM_RET_t 
cbb_soft_tim_monitor(Soft_Tim_t* pstTim){

    // 输入参数检查
    if(NULL == pstTim) return SOFT_TIM_ERR;

    // 提取定时器标志位和周期
    uint16_t u16Interval = pstTim->u16Interval;
    uint16_t u16FLag = pstTim->u16Flag;

    // 定时器使能位检查,超时标志位检查 -- 超时未处理暂停计时
    if( (u16FLag & (0x01 << SOFT_TIM_EN_BIT)) == 0 || 
        (u16FLag & (0x01 << SOFT_TIM_TIMOUT)) == 1) return SOFT_TIM_OK;

    // 定时器计数
    pstTim->u16Tick++;

    // 大于定时器周期，产生定时器事件
    if(pstTim->u16Tick >= u16Interval){

        // 清除tick
        pstTim->u16Tick = 0;

        // 更新定时器事件
        u16FLag |= (0x01 << SOFT_TIM_TIMOUT);
    }
    
    // 定时器状态更新
    pstTim->u16Flag = u16FLag;

    // 返回成功
    return SOFT_TIM_OK;
}


SOFT_TIM_RET_t
cbb_soft_tim_set_interval(Soft_Tim_t* pstTim, uint16_t u16Interval){

    // 输入参数检查
    if(NULL == pstTim) return SOFT_TIM_ERR;
        
    // 定时器周期更新
    pstTim->u16Interval = u16Interval;

    // 返回成功
    return SOFT_TIM_OK;
}

SOFT_TIM_RET_t 
cbb_soft_tim_enable(Soft_Tim_t* pstTim, uint8_t u8Enable){

    // 输入参数检查
    if(NULL == pstTim) return SOFT_TIM_ERR;

    // 提取定时器标志位和周期
    uint16_t u16FLag = pstTim->u16Flag;

    // 定时器使能
    (u8Enable) ? (u16FLag |= (0x01 << SOFT_TIM_EN_BIT)) : (u16FLag &= ~(0x01 << SOFT_TIM_EN_BIT));

    // 清空计数
    (u8Enable) ? (pstTim->u16Tick = pstTim->u16Tick) : (pstTim->u16Tick = 0);
    
    // 定时器状态更新
    pstTim->u16Flag = u16FLag;

    // 定时器周期更新
    return SOFT_TIM_OK;
}

uint8_t 
cbb_soft_tim_timeout(Soft_Tim_t* pstTim){

    // 输入参数检查
    if(NULL == pstTim) return 0;

    // 提取定时器标志位
    uint16_t u16FLag = pstTim->u16Flag;

    // 定时器超时标志位检查
    return u16FLag & (0x01 << SOFT_TIM_TIMOUT);
}

SOFT_TIM_RET_t
cbb_soft_tim_clear_timeout(Soft_Tim_t* pstTim){

    // 输入参数检查
    if(NULL == pstTim) return SOFT_TIM_ERR;

    // 提取定时器标志位
    uint16_t u16FLag = pstTim->u16Flag;

    // 定时器超时标志位清除
    u16FLag &= ~(0x01 << SOFT_TIM_TIMOUT);

    // 定时器状态更新
    pstTim->u16Flag = u16FLag;

    // 返回成功
    return SOFT_TIM_OK;
}
